package com.zwh.se.collection.concurrent;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author yexi
 * 验证一下ArrayList的线程不安全问题,并通过Collections.synchronizedList方式将其转换为线程安全的集合
 */
@SuppressWarnings({"unchecked","rawtypes"})
public class SynchronizedListDemo {
    public static void main(String[] args) throws InterruptedException {
        ArrayList list = new ArrayList();
        //创建一个线程池：线程池定长100
        ExecutorService es = Executors.newFixedThreadPool(100);
        //并发向集合中添加10000个数据：
        for (int i = 0; i < 10000; i++) {
            //每个线程处理任务：run方法中的内容就是线程单元，任务，实际线程执行的部分
            es.execute(new Runnable() {
                @Override
                public void run() {
                    list.add("aaa");
                }
            });
        }
        //关闭线程池：
        es.shutdown();
        //监控线程是否执行完毕：
        while (true) {
            //线程都执行完以后返回true
            if (es.isTerminated()) {
                System.out.println("所有的子线程都执行完毕了！");
                //执行完毕以后看一下集合中元素的数量：
                System.out.println(list.size());
                if (list.size() == 10000) {
                    System.out.println("线程安全！");
                } else {
                    System.out.println("线程不安全！");
                }
                //线程执行完以后，while循环可以停止：
                break;
            }
        }

        Thread.sleep(4000);

        ArrayList oldList = new ArrayList();
        /**
         * @see Collections#synchronizedList(List list)
         * @see
         * @see Collections.SynchronizedRandomAccessList#SynchronizedRandomAccessList(List list)
         *             super(list);
         * @see Collections.SynchronizedCollection#SynchronizedCollection(Collection c)
         *             // 此处的c就是原来的那个arrayList
         *             this.c = Objects.requireNonNull(c);
         *             // 充当共享对象,也就是作为锁,而this就是当前的这个同步类容器
         *             mutex = this;
         */
        List synchronizedList = Collections.synchronizedList(oldList);
        //创建一个线程池：线程池定长100
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        //并发向集合中添加10000个数据：
        for (int i = 0; i < 10000; i++) {
            //每个线程处理任务：run方法中的内容就是线程单元，任务，实际线程执行的部分
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    /**
                     * @see Collections.SynchronizedCollection#add(Object e)
                     *           //底层还是走的ArrayList的add(),但是在外层套了一个同步代码块
                     *             synchronized (mutex) {return c.add(e);}
                     */
                    synchronizedList.add("aaa");
                }
            });
        }
        //关闭线程池：
        executorService.shutdown();
        //监控线程是否执行完毕：
        while (true) {
            //线程都执行完以后返回true
            if (executorService.isTerminated()) {
                System.out.println("所有的子线程都执行完毕了！");
                //执行完毕以后看一下集合中元素的数量：
                System.out.println(synchronizedList.size());
                if (synchronizedList.size() == 10000) {
                    System.out.println("线程安全！");
                } else {
                    System.out.println("线程不安全！");
                }
                //线程执行完以后，while循环可以停止：
                break;
            }
        }
    }

}


